package com.gzc.just.play.last.war.sceneserver.damage;

import com.gzc.just.play.last.war.sceneserver.gameobject.unit.GameUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

/**
 * 伤害计算器 - 处理所有伤害计算逻辑
 * 
 * 对应C++ ActuelDamageCalculate相关逻辑
 * 
 * @author AI Assistant
 * @version 1.0.0
 * @since 2025-11-22
 */
public class DamageCalculator {
    
    private static final Logger log = LoggerFactory.getLogger(DamageCalculator.class);
    private final Random random = new Random();
    
    // 单例模式
    private static final DamageCalculator INSTANCE = new DamageCalculator();
    
    public static DamageCalculator getInstance() {
        return INSTANCE;
    }
    
    private DamageCalculator() {}
    
    // 默认系数
    private static final float BASE_DEFENSE_REDUCTION_RATE = 0.5f;  // 防御力抵消率
    private static final float CRITICAL_MULTIPLIER = 1.5f;           // 暴击倍数
    private static final float MIN_DAMAGE_MULTIPLIER = 0.1f;         // 最小伤害倍数
    private static final int MIN_FINAL_DAMAGE = 1;                   // 最小伤害
    
    /**
     * 计算最终伤害
     * 
     * @param attacker 攻击者
     * @param defender 防守者
     * @param baseDamage 基础伤害
     * @param damageType 伤害类型
     * @return 伤害结果
     */
    public static DamageResult calculateDamage(GameUnit attacker, GameUnit defender, 
                                             int baseDamage, DamageType damageType) {
        return getInstance().calculateDamageInternal(attacker, defender, baseDamage, damageType);
    }
    
    /**
     * 内部计算方法（实例方法）
     */
    private DamageResult calculateDamageInternal(GameUnit attacker, GameUnit defender, 
                                               int baseDamage, DamageType damageType) {
        DamageResult result = new DamageResult(attacker.getObjectId(), defender.getObjectId(), 
                                              baseDamage, baseDamage, baseDamage, baseDamage,
                                              damageType, false, 1.0f, false, false, false, 
                                              System.currentTimeMillis(), "基础伤害");
        
        // 验证有效性
        if (baseDamage <= 0) {
            return new DamageResult(attacker.getObjectId(), defender.getObjectId(), 
                                   0, 0, 0, 0,
                                   damageType, false, 1.0f, false, false, false, 
                                   System.currentTimeMillis(), baseDamage == 0 ? "零伤害" : "无效伤害");
        }
        
        // 步骤1：基础伤害
        int damage = baseDamage;
        
        // 步骤2：检查躲避
        if (checkDodge(defender)) {
            return new DamageResult(attacker.getObjectId(), defender.getObjectId(), 
                                   0, 0, 0, 0, 
                                   damageType, false, 1.0f, false, true, false, 
                                   System.currentTimeMillis(), "躲避");
        }
        
        // 步骤3：应用加成
        damage = applyBonus(damage, attacker, defender, damageType);
        
        // 步骤4：应用防御
        if (damageType.canBeDefended()) {
            damage = applyDefense(damage, defender);
        }
        
        // 步骤5：检查暴击
        boolean isCritical = checkCritical(attacker);
        if (isCritical) {
            damage = (int)(damage * CRITICAL_MULTIPLIER);
        }
        
        // 步骤6：最小伤害检查
        damage = Math.max(MIN_FINAL_DAMAGE, damage);
        
        // 创建最终结果
        return new DamageResult(attacker.getObjectId(), defender.getObjectId(), 
                              baseDamage, damage, damage, damage,
                              damageType, isCritical, CRITICAL_MULTIPLIER, false, false, false, 
                              System.currentTimeMillis(), 
                              isCritical ? "暴击" : "普通伤害");
    }
    
    /**
     * 计算技能伤害
     * 
     * @param attacker 攻击者
     * @param defender 防守者
     * @param skillId 技能ID
     * @param skillDamageRate 技能伤害倍率
     * @return 伤害结果
     */
    public static DamageResult calculateSkillDamage(GameUnit attacker, GameUnit defender,
                                                    int skillId, float skillDamageRate) {
        // 基础伤害 = 攻击力 * 技能倍率
        int baseDamage = (int)(attacker.getAttack() * skillDamageRate);
        DamageResult result = calculateDamage(attacker, defender, baseDamage, DamageType.MAGICAL);
        result.setDamageReason("技能 #" + skillId);
        return result;
    }
    
    /**
     * 计算普通攻击伤害
     * 
     * @param attacker 攻击者
     * @param defender 防守者
     * @return 伤害结果
     */
    public static DamageResult calculateNormalAttackDamage(GameUnit attacker, GameUnit defender) {
        DamageCalculator instance = getInstance();
        // 普通攻击伤害 = 攻击力 * (0.8 - 1.2)
        int baseDamage = (int)(attacker.getAttack() * (0.8f + instance.random.nextFloat() * 0.4f));
        DamageResult result = calculateDamage(attacker, defender, baseDamage, DamageType.PHYSICAL);
        result.setDamageReason("普通攻击");
        return result;
    }
    
    /**
     * 检查躲避
     */
    private boolean checkDodge(GameUnit defender) {
        // 躲避率 = 速度 / 500
        float dodgeRate = Math.min(0.5f, (float)(defender.getSpeed() / 500.0));
        return random.nextFloat() < dodgeRate;
    }
    
    /**
     * 应用加成
     */
    private static int applyBonus(int damage, GameUnit attacker, GameUnit defender, DamageType damageType) {
        float totalBonus = 1.0f;
        
        // 基于伤害类型的加成
        switch (damageType) {
            case PHYSICAL:
                // 物理伤害受攻击力影响
                totalBonus = 1.0f + (float)(attacker.getAttack() / 100.0) * 0.1f;
                break;
            case MAGICAL:
                // 魔法伤害受智力影响（如果有的话）
                totalBonus = 1.0f;
                break;
            case PURE:
            case TRUE_DAMAGE:
                // 纯伤害不受加成
                totalBonus = 1.0f;
                break;
            default:
                totalBonus = 1.0f;
        }
        
        // 保证倍数在合理范围
        totalBonus = Math.max(MIN_DAMAGE_MULTIPLIER, totalBonus);
        
        return (int)(damage * totalBonus);
    }
    
    /**
     * 应用防御
     */
    private static int applyDefense(int damage, GameUnit defender) {
        // 防御力抵消伤害
        // 最终伤害 = 基础伤害 - (防御力 * 抵消率)
        int defenseReduction = (int)(defender.getDefense() * BASE_DEFENSE_REDUCTION_RATE);
        int finalDamage = damage - defenseReduction;
        
        // 伤害最低为基础伤害的10%，或者至少为1
        finalDamage = Math.max(Math.max((int)(damage * MIN_DAMAGE_MULTIPLIER), MIN_FINAL_DAMAGE), finalDamage);
        
        return finalDamage;
    }
    
    /**
     * 检查暴击
     */
    private boolean checkCritical(GameUnit attacker) {
        // 暴击率来自单位的暴击率属性
        return random.nextFloat() < attacker.getCriticalRate();
    }
    
    /**
     * 计算真实伤害（不能被防御）
     */
    public static DamageResult calculateTrueDamage(GameUnit attacker, GameUnit defender, int damage) {
        DamageResult result = new DamageResult(attacker.getObjectId(), defender.getObjectId(), 
                                          damage, damage, damage, damage,
                                          DamageType.TRUE_DAMAGE, false, 1.0f, false, false, false, 
                                          System.currentTimeMillis(), "真实伤害");
        return result;
    }
    
    /**
     * 计算治疗效果
     */
    public static DamageResult calculateHealing(GameUnit healer, GameUnit target, int healAmount) {
        DamageResult result = new DamageResult(healer.getObjectId(), target.getObjectId(), 
                                          -healAmount, -healAmount, -healAmount, -healAmount,
                                          DamageType.HEAL, false, 1.0f, false, false, false, 
                                          System.currentTimeMillis(), "治疗");
        return result;
    }
}